/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import React, {
  Fragment,
  useEffect,
  useCallback,
  useState,
  useRef
} from 'react'
import { CSSTransition } from 'react-transition-group'
import { useHistory } from 'react-router-dom'
import { ToastNotification } from '@/components/Toast'
import { DEVLAKE_ENDPOINT } from '@/utils/config'
import request from '@/utils/request'
import {
  H2,
  Button,
  Icon,
  Intent,
  Card,
  Elevation,
  Tag,
  Tooltip,
  Position,
  Spinner,
  Colors
} from '@blueprintjs/core'
import { ReactComponent as Logo } from '@/images/devlake-logo.svg'
import { ReactComponent as LogoText } from '@/images/devlake-textmark.svg'
import '@/styles/offline.scss'

const Offline = (props) => {
  const { pollTimer = 7000, retryLimit = 100, endpointUrl = null } = props
  const history = useHistory()
  const testInterval = useRef()
  const retryCount = useRef()

  const [apiEndpointUrl, setApiEndpointUrl] = useState(
    `${DEVLAKE_ENDPOINT}/ping`
  )
  const [isOffline, setIsOffline] = useState(true)
  const [testResponse, setTestResponse] = useState({})
  const [testStatus, setTestStatus] = useState(504)
  const [cardReady, setCardReady] = useState(false)
  // eslint-disable-next-line no-unused-vars
  const [aborted, setAborted] = useState(false)

  const testEndpoint = useCallback(async () => {
    console.log('>> OFFLINE MODE -  TESTING ENDPOINT!', apiEndpointUrl)
    retryCount.current++
    try {
      setCardReady(false)
      const t = await request.get(apiEndpointUrl)
      setTestResponse(t.data)
      setTestStatus(() => t.status ?? 504)
    } catch (e) {
      setTestResponse((tR) => {
        return {
          ...tR,
          data: [],
          error: e.response.data,
          statusCode: e.response.status
        }
      })
      setTestStatus(504)
    }
  }, [apiEndpointUrl])

  useEffect(() => {
    console.log('>> OFFLINE MODE -  ENDPOINT TEST RESPONSE = ', testResponse)
    if (testResponse?.error) {
      ToastNotification.clear()
      ToastNotification.show({
        message: testResponse.error ?? 'Network Error 504 (Gateway Timeout)',
        intent: 'danger',
        icon: 'error'
      })
    }
    setTimeout(() => {
      setCardReady(true)
    }, 0)
  }, [testResponse])

  useEffect(() => {
    console.log('>> OFFLINE MODE - CURRENT API HTTP/STATUS: ', testStatus)
    setIsOffline(testStatus !== 200)
    if (testStatus === 200) {
      clearInterval(testInterval.current)
      ToastNotification.clear()
      ToastNotification.show({
        message: 'DevLake API Online',
        intent: 'danger',
        icon: 'tick-circle'
      })
      console.log('>> OFFLINE MODE - API RESTORED, TERMINATING POLLING!!!')
    }
  }, [testStatus])

  useEffect(() => {
    console.log('>> OFFLINE MODE -  OFFLINE CHECK?', isOffline)
  }, [isOffline])

  useEffect(() => {
    testEndpoint()
  }, [testEndpoint])

  useEffect(() => {
    testInterval.current = setInterval(() => {
      setTestStatus(504)
      testEndpoint()
      // retryCount.current++
    }, pollTimer)

    return () => {
      clearInterval(testInterval.current)
      setCardReady(false)
      setAborted(false)
    }
  }, [pollTimer, testEndpoint])

  useEffect(() => {
    console.log('>> OFFLINE MODE (MOUNTED) - ENDPOINT URL ...', endpointUrl)
    retryCount.current = 1
    setAborted(false)
    setApiEndpointUrl((url) =>
      endpointUrl !== null && endpointUrl !== url
        ? endpointUrl
        : `${DEVLAKE_ENDPOINT}/ping`
    )
  }, [endpointUrl])

  useEffect(() => {
    if (retryCount.current >= retryLimit) {
      console.log(
        '>> OFFLINE MODE - RETRY LIMIT EXCEEDED, TERMINATING POLLING!!!'
      )
      clearInterval(testInterval.current)
      setAborted(true)
      ToastNotification.clear()
      ToastNotification.show({
        message: 'Retry Limit Exceeded, please refresh your browser.',
        intent: 'danger',
        icon: 'error'
      })
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [retryCount.current, retryLimit])

  return (
    <>
      {
        <div
          className={`offline-wrapper ${
            isOffline ? 'is-offline' : 'is-online'
          }`}
        >
          <div
            style={{
              maxWidth: '500px',
              margin: '0 auto',
              display: 'flex',
              height: '100%',
              flexDirection: 'column'
            }}
          >
            <div style={{ margin: 'auto auto', padding: '16px' }}>
              <div className='devlake-logo' style={{ margin: 0 }}>
                <Logo width={48} height={48} className='logo' />
                <LogoText width={100} height={13} className='logo-textmark' />
              </div>
              <CSSTransition
                in={cardReady}
                timeout={900}
                classNames='offline-card'
              >
                <Card elevation={Elevation.THREE}>
                  <span
                    style={{
                      display: 'block',
                      position: 'absolute',
                      right: 0,
                      top: 0,
                      margin: '10px'
                    }}
                  >
                    {isOffline ? (
                      <Spinner size={16} />
                    ) : (
                      <Icon icon='tick-circle' size={16} color={Colors.GRAY4} />
                    )}
                  </span>
                  <div style={{ textAlign: 'center' }}>
                    {isOffline ? (
                      <img
                        style={{
                          margin: '0px auto 10px auto',
                          width: '54px',
                          height: '54px',
                          maxWidth: '5 4px'
                        }}
                        width={54}
                        height={54}
                        // eslint-disable-next-line max-len
                        src=''
                      />
                    ) : (
                      <img
                        style={{
                          margin: '0px auto 10px auto',
                          width: '64px',
                          height: '64px',
                          maxWidth: '64px'
                        }}
                        width={64}
                        height={64}
                        // eslint-disable-next-line max-len
                        src=''
                      />
                    )}
                  </div>
                  <H2>
                    DevLake API&nbsp;
                    <CSSTransition
                      in={cardReady}
                      timeout={300}
                      classNames='offline-card-os'
                    >
                      {isOffline ? (
                        <strong
                          style={{
                            padding: '0 3px',
                            fontWeight: '900',
                            backgroundColor: 'rgba(220,50,50,0.2)',
                            color: 'rgb(212, 69, 36)'
                          }}
                        >
                          Offline
                        </strong>
                      ) : (
                        <strong
                          style={{
                            padding: '0 3px',
                            fontWeight: '900',
                            backgroundColor: 'rgba(50,221,80,0.2)',
                            color: 'rgb(36, 212, 72)'
                          }}
                        >
                          Online
                        </strong>
                      )}
                    </CSSTransition>
                  </H2>
                  <Tag>
                    <code>DEVLAKE_ENDPOINT: {DEVLAKE_ENDPOINT}</code>
                  </Tag>
                  {isOffline ? (
                    <>
                      <p style={{ fontSize: '16px', color: '#222222' }}>
                        Please wait for the&nbsp;
                        <strong>Lake API</strong> to start before accessing the{' '}
                        <strong>Configuration Interface</strong>.
                      </p>
                      <Tooltip
                        intent={Intent.PRIMARY}
                        className='offline-continue-tooltip'
                        targetClassName='offline-continue-tooltip-target'
                        content={
                          <>
                            <Icon size={14} icon='warning-sign' /> Proceed with
                            caution.
                          </>
                        }
                        position={Position.RIGHT}
                        style={{ cursor: 'pointer' }}
                      >
                        <Button
                          intent={Intent.PRIMARY}
                          icon='warning-sign'
                          style={{ fontWeight: 700 }}
                          onClick={() => history.replace('/')}
                        >
                          Continue
                        </Button>
                      </Tooltip>
                      <Button
                        icon='refresh'
                        text='Refresh'
                        minimal
                        style={{ marginLeft: '5px' }}
                        disabled={!cardReady}
                        onClick={() => testEndpoint()}
                      />
                    </>
                  ) : (
                    <>
                      <p style={{ fontSize: '16px', color: '#222222' }}>
                        Connectivity to the Lake API service was successful.
                      </p>
                      <Button
                        icon='cog'
                        intent={Intent.PRIMARY}
                        onClick={() => history.replace('/')}
                      >
                        Open Dashboard
                      </Button>
                      <a
                        href='https://github.com/apache/incubator-devlake/blob/main/README.md'
                        target='_blank'
                        rel='noreferrer'
                        style={{ marginLeft: '5px' }}
                        className='bp3-button bp3-minimal'
                      >
                        <Icon
                          icon='help'
                          size={16}
                          style={{ marginRight: '5px' }}
                        />
                        Read Documentation
                      </a>
                    </>
                  )}
                </Card>
              </CSSTransition>
              <div
                style={{
                  margin: '10px 5px 10px 5px',
                  display: 'flex',
                  justifyContnt: 'flex-start'
                }}
              >
                <div style={{ color: 'rgba(33, 33, 33, 0.6)' }}>
                  {isOffline ? (
                    <>
                      <strong style={{ fontWeight: 900, letterSpacing: '2px' }}>
                        OFFLINE &middot;&nbsp;
                      </strong>
                      <a
                        href='https://github.com/apache/incubator-devlake/blob/main/README.md'
                        target='_blank'
                        rel='noreferrer'
                        style={{ fontWeight: 400, letterSpacing: 0 }}
                      >
                        Documentation on{' '}
                        <span style={{ fontWeight: 800 }}>GitHub</span>
                      </a>
                      <br /> Please verify network connectivity if the problem
                      persists.
                      <br />
                      <strong style={{ fontWeight: 600, letterSpacing: '0px' }}>
                        {retryCount.current} failed attempt(s).
                      </strong>
                    </>
                  ) : (
                    <>
                      <strong style={{ fontWeight: 900, letterSpacing: '2px' }}>
                        ONLINE &middot;&nbsp;
                      </strong>
                      <a
                        href='/integrations'
                        style={{
                          color: 'rgba(50,50,50,0.6)',
                          textDecoration: 'underline',
                          fontWeight: 400,
                          letterSpacing: 0
                        }}
                      >
                        Proceed with{' '}
                        <span style={{ fontWeight: 800 }}>
                          Data Connections
                        </span>
                      </a>
                      <br /> Lake API connection restored.
                    </>
                  )}
                </div>
              </div>
            </div>
          </div>
        </div>
      }
    </>
  )
}

export default Offline
